// main layer
var g_mainLayer=null;
var MainLayer = cc.Layer.extend({
    ////////////////////////////
    // data object
    _mapObject : null,
    _towerObject : null,
    _enemyObject : null,
    ////////////////////////////
    // instance award buffer
    _jsonMap : null,
    _enemyProxy : null,
    // ( user can choose )tower parent and buffer
    _towerVessel : null,
    // update update tower
    _targetProxy : null,
    _placeProxy : null,
    _updateProxy : null,
    // all bullet buffer for update it,different from tower's bullet buffer
    _bullets : null,
    ctor:function () {
        this._super();
        g_mainLayer=this;
        g_mainLayer.retain();
        this._bullets = new Array();
        this.initObjects();
        this.addTouchEvent();
        return true;
    },
    onEnter:function () {
        this._super();
        this.addJsonMap();
        this.addTowerVessel();
        this.addEnemyProxy();
        this.addTargetProxy();
        this.addTowerProxy();
        // update
        this.scheduleUpdate();
        // emission
        this._enemyProxy.emission();
    },
    onExit : function(){
        var length = this._bullets.length;
        for( var i=0;i<length;i++) {
            var bullet = this._bullets[i];
            if( bullet ){
                bullet.removeFromParent(true);
            }
        }
        this._bullets.splice(0,length);
        this._super();
    },
    /////////////////////////////////////////////////////////////////////
    initObjects : function(){
        this._mapObject=GetLevelMap(g_gameLevel);
        this._towerObject=GetLevelTower(g_gameLevel);
        this._enemyObject=GetLevelEnemy(g_gameLevel);
    },
    //////////////////////////////////////////////////////////////////////
    addBullet : function(bullet){
        this.addChild(bullet,10 );
        this._bullets.push(bullet);
    },
    /////////////////////////////////////////////////////////////////////
    addTouchEvent : function() {
        cc.eventManager.addListener({
            event: cc.EventListener.TOUCH_ONE_BY_ONE,
            swallowTouches: true,
            onTouchBegan: this.onTouchBegan
        }, this);
    },
    onTouchBegan : function (touch, event) {
        ShowPlacePanel( touch.getLocation() );
        return true;
    },
    /////////////////////////////////////////////////////////////////////
    addJsonMap : function(){ // award + road
        this._jsonMap = JsonMap.createWithJsonObject(this._mapObject);
        //this._jsonMap = JsonMap.createWithJsonFile("res/map/map"+g_gameLevel+".json");
        this.addChild( this._jsonMap,MW.MORDER.MAP );
    },
    addTowerVessel : function(){ // towers
        this._towerVessel = new TowerVessel();
        this._towerVessel.setPosition( cc.p(0,0) );
        this.addChild( this._towerVessel,MW.MORDER.TOWER );
    },
    addEnemyProxy : function(){
        this._enemyProxy = new EnemyProxy();
        this.addChild( this._enemyProxy,MW.MORDER.ENEMY );
    },
    addTargetProxy:function() { // proxy
        this._targetProxy = new TargetProxy();
        this.addChild( this._targetProxy,MW.MORDER.TARGET );
    },
    addTowerProxy:function(){ // proxy
        this._placeProxy = new PlaceProxy();
        this.addChild( this._placeProxy,MW.MORDER.TPROXY );
        this._updateProxy = new UpdateProxy();
        this.addChild( this._updateProxy,MW.MORDER.TPROXY );
    },
    //////////////////////////////////////////////////////////////////////
    update:function(dt){
        var enemies = this._enemyProxy.getEnemies(),emptyEnemy=true;
        var towers = this._towerVessel.getTowers();
        var awards = this._jsonMap.getAwardArray();
        for ( var i=0;i<enemies.length;++i){
            var enemy = enemies[i];
            if(true==emptyEnemy)emptyEnemy = false;
            if(enemy._life){
                enemy.moving(dt);
                var enePos = enemy.getPosition();
                // checking direct col with point
                var directArr = this._jsonMap.getDirectArray();
                for ( var d=0;d<directArr.length;d++){
                    var direct = directArr[d];
                    var directType = direct.direct();
                    if( directType!=enemy._directType && cc.rectContainsPoint( direct.collideRect(
                        direct.getPositionX(),direct.getPositionY()),enePos )  ){
                        cc.log("orig direct type: "+enemy._directType);
                        enemy._directType = directType;
                        enemy.direct( directType );
                        cc.log("coll direct type: "+enemy._directType);
                    }
                }
                //////////////////////chooser/////////////////////////////
                for ( var t=0;t<towers.length;++t){
                    var tower = towers[t];
                    if (tower){
                        if( null!=g_chooser && tower.fighting( g_chooser.getPosition() ) ){
                            continue;
                        }
                        tower.fighting( enemy.getPosition() );
                    }
                }
                // coll with role
                var role = GetRole();
                if( role ){
                    var rolPos = role.getPosition();
                    if ( cc.rectIntersectsRect( enemy.collideRect(enePos.x,enePos.y),
                        role.collideRect(rolPos.x,rolPos.y)) ){
                        cc.log("col role ");
                        enemy.dead();
                        role.hurt();
                    }
                }
            }else{
                enemies.splice(i,1);
                JudgeGameState();
            }
        }
        //////////////////////chooser/////////////////////////////
        if(true==emptyEnemy){
            for ( var t=0;t<towers.length;++t){
                var tower = towers[t];
                if (tower){
                    if( null!=g_chooser && tower.fighting( g_chooser.getPosition() ) ){
                        continue;
                    }
                }
            }
        }

        //////////////////////////update bullet//////////////////////////////
        var bullets = this._bullets;
        for ( var b=0;b<bullets.length;b++) {
            var bullet = bullets[b];
            if (bullet._life==true) {
                bullet.moving(dt);
                // bullet enemy col checking
                for ( var i=0;i<enemies.length;++i) {
                    var enemy = enemies[i];
                    if (enemy._life) {
                        this.collideModule(enemy,bullet);
                    }
                }
                // bullet award col checking
                for ( var j=0;j<awards.length;++j) {
                    var award = awards[j][0];
                    if (award._life) {
                        this.collideModule(award,bullet);
                    }else{
                        awards.splice(j,1); // here is a little bug
                    }
                }
            }else{
                // when bullet dead and it's parent been removed just remove itself too
                if( null==bullet.getOwner() ){
                    cc.log( "********remove bullet from main layer: "+bullet.getType() );
                    bullet.removeFromParent(true);
                    bullets.splice(b,1);
                }
            }
        }
    },
    collideModule : function( target,bullet ){
        var type = bullet.getType();
        switch(type){
            case 0: {
                if (bullet._collide) {
                    var enePos = target.getPosition(),bulPos = bullet.getPosition();
                    if ( ( (enePos.x-bulPos.x)*(enePos.x-bulPos.x)+
                        (enePos.y-bulPos.y)*(enePos.y-bulPos.y) ) < bullet._scope*bullet._scope ){
                        cc.log("bullet a collision with target" );
                        if ( target.hurt(bullet.getPower()) ){
                            PlayEnemyDeadEffect( enePos );
                        }
                    }
                }
                break;
            }
            case 1: {
                var enePos = target.getPosition(),bulPos = bullet.getPosition();
                if ( cc.rectIntersectsRect( target.collideRect(enePos.x,enePos.y),bullet.collideRect(bulPos.x,bulPos.y)) ){
                    cc.log("bullet collision with target" );
                    bullet.recover();
                    if ( target.hurt(bullet.getPower()) ){
                        PlayEnemyDeadEffect( enePos );
                    }
                }
                break;
            }
            case 2: {
                if( !bullet.findTarget( target ) ){
                    var enePos = target.getPosition(),bulPos = bullet.getPosition();
                    if ( cc.rectIntersectsRect( target.collideRect(enePos.x,enePos.y),bullet.collideRect(bulPos.x,bulPos.y)) ){
                        cc.log("bullet collision with target" );
                        bullet.pushTargetBack(target);
                        if ( target.hurt(bullet.getPower()) ){
                            PlayEnemyDeadEffect( enePos );
                        }
                    }
                }
                break;
            }

        }
    }
});

///////////////////////////////////////////////
GetMainLayer=function(){
    if(g_mainLayer){
        cc.log("*** get main layer down");
        return g_mainLayer;
    }else{
        cc.log("*** invalid g_mainLayer");
    }
}
AddMainLayer=function(parent){
    if(parent){
        var layer = new MainLayer();
        parent.addChild( layer,5 );
        cc.log("*** add main layer down");
    }else{
        cc.log("*** invalid parent");
    }
}
RemoveMainLayer=function(clear){
    if(g_mainLayer){
        g_mainLayer.removeFromParent(clear);
        cc.log("*** remove main layer down, clear: "+clear);
    }else{
        cc.log("g_mainLayer is invalid");
    }
}
/////////////////////////////////////////////
GetMainLayer=function(clear){
    if(g_mainLayer){
        return g_mainLayer;
    }else{
        cc.log("g_mainLayer is invalid");
    }
}
//////////////////////////////////////////////
GetMapObject=function(){
    if(g_mainLayer){
        cc.log("getting map object ");
        return g_mainLayer._mapObject;
    }else{
        cc.log("g_mainLayer is invalid");
    }
}
GetTowerObject=function(){
    if(g_mainLayer){
        cc.log("getting tower object ");
        return g_mainLayer._towerObject;
    }else{
        cc.log("g_mainLayer is invalid");
    }
}
GetEnemyObject=function(){
    if(g_mainLayer){
        cc.log("getting enemy object ");
        return g_mainLayer._enemyObject;
    }else{
        cc.log("g_mainLayer is invalid");
    }
}

/////////////////////////////////////////////
GetTowerPa=function(){
    if(g_mainLayer){
        cc.log("getting tower pa instance ");
        return g_mainLayer._towerVessel;
    }else{
        cc.log("g_mainLayer is invalid");
    }
}